package com.allwees.bs.module.pms.score.model;

import com.allwees.bs.module.pms.score.FactorFun;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.math.util.MathUtils;

/**
 * Score项定义
 *
 * @author yangylsky
 * @since 2020-03-12
 *
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class ScoreFactor {
	/**
	 * 权重
	 */
	private Double weight;

	/**
	 * 有效值下限
	 */
	private Double min;

	/**
	 * 拐点值
	 */
	private Double inflection;

	/**
	 * 有效值上限
	 */
	private Double max;

	/**
	 * x < min 的算法
	 */
	private FactorFun fun0;

	/**
	 * min <= x < inflection 的算法
	 */
	private FactorFun fun1;

	/**
	 * inflection <= x < max 的算法
	 */
	private FactorFun fun2;

	/**
	 * max <= x 的算法
	 */
	private FactorFun fun3;

	/**
	 * 计算单项Score(with weight)
	 *
	 * @param x
	 * @return
	 */
	public Double caculateScore(Double x) {
		return MathUtils.round(caculateOriginScore(x) * weight, 14);
	}


	/**
	 * 计算单项Score(without weight)
	 *
	 * @param x
	 * @return
	 */
	public Double caculateOriginScore(Double x) {
		double _minScore = fun0.caculate(min - Double.MIN_VALUE);
		double _inflectionScore = _minScore + fun1.caculate(inflection - Double.MIN_VALUE);
		double _maxScore = _inflectionScore +fun2.caculate(max - Double.MIN_VALUE);
		double result = 0.0;
		if(x == null || x < min) {
			result = fun0.caculate(x);
		} else if(min <= x && x < inflection) {
			result = _minScore + fun1.caculate(x);
		} else if(inflection <= x && x < max) {
			result = _inflectionScore + fun2.caculate(x);
		} else if(max <= x) {
			result = _maxScore + fun3.caculate(x);
		} else {
			throw new IllegalArgumentException("参数错误: " + x);
		}
		return MathUtils.round(result, 15);
	}

	public String printOriginScores() {
		return "{" + StringUtils.rightPad(weight.toString(), 4, '0')  + ": "
				+ " [" + min + ": " + caculateOriginScore(min + Double.MIN_VALUE)
				+ "], [" + inflection + ": " + caculateOriginScore(inflection + Double.MIN_VALUE)
				+ "], [" + max + ": " + caculateOriginScore(max + Double.MIN_VALUE) + "]}";
	}
}
